home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
msoftapp.zip
/
BOUNCE.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-01
|
7KB
|
271 lines
// bounce.cpp : Defines the class behaviors for the Bounce child window.
#include"viewer.h"
BEGIN_MESSAGE_MAP(CBounceWin, CMDIChildWnd)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_TIMER()
ON_WM_MDIACTIVATE()
ON_COMMAND(IDM_BLACK, OnColor)
ON_COMMAND(IDM_RED, OnColor)
ON_COMMAND(IDM_GREEN, OnColor)
ON_COMMAND(IDM_BLUE, OnColor)
ON_COMMAND(IDM_WHITE, OnColor)
ON_COMMAND(IDM_CUSTOM, OnColor)
ON_COMMAND(IDM_SLOW, OnSpeed)
ON_COMMAND(IDM_FAST, OnSpeed)
END_MESSAGE_MAP()
// COULD BE REPLACED WITH TEMPLATE
#define ABS(x) ((x) < 0? -(x) : (x) > 0? (x) : 0)
// Create: register custom WndClass and create a window.
// This must be done because CBounceWin has a custom cursor.
BOOL CBounceWin::Create(LPCSTR szTitle, DWORD style, const RECT& rect,
CMDIFrameWnd* parent)
{
const char* pszBounceClass = // register a custom Window class
AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
LoadCursor(NULL, IDC_UPARROW),
(HBRUSH)(COLOR_WINDOW+1),
NULL);
return CMDIChildWnd::Create(pszBounceClass, szTitle, style, rect, parent);
}
CBounceWin::CBounceWin(void)
{
m_pBitmap = NULL;
m_pMenuCurrent = NULL;
m_bWindowActive = FALSE;
m_nColor = IDM_BLACK;
m_clrBall = clrTextArray[m_nColor - IDM_BLACK];
}
CBounceWin::~CBounceWin(void)
{
// Suppress Foundation DestroyMenu done in CMenu destructor
// (Windows takes care of menu cleanup for the active window)
if(m_bWindowActive)
m_pMenuCurrent->Detach();
delete m_pBitmap;
if(m_nSpeed != 0)
KillTimer(1);
}
// OnCreate: Set up the ball parameters and start a timer.
int CBounceWin::OnCreate(LPCREATESTRUCT)
{
m_nSpeed = IDM_SLOW;
if(!SetTimer(1,(m_nSpeed == IDM_SLOW ? 100 : 0), NULL))
{
MessageBox("Not enough timers available for this window.",
"Viewer | Bounce", MB_ICONEXCLAMATION | MB_OK);
m_nSpeed = 0;
return -1; // signal creation failure...
}
else
{
CDC* pDC = GetDC();
m_xPixel = pDC->GetDeviceCaps(ASPECTX);
m_yPixel = pDC->GetDeviceCaps(ASPECTY);
ReleaseDC(pDC);
// Note that we could call MakeNewBall here (which should be called
// whenever the ball's speed, color or size has been changed), but the
// OnSize member function is always called after the OnCreate. Since
// the OnSize member has to call MakeNewBall anyway, we don't here.
}
return 0;
}
// OnDestroy:
// Notify app main MDI frame window of destruction so it may
// do some cleanup.
void CBounceWin::OnDestroy(void)
{
GetMDIFrame()->SendMessage(WM_CHILDDESTROY,(UINT)m_hWnd, 0);
}
// MakeNewBall:
// Whenever a parameter changes which would affect the speed or appearance
// of the ball, call this to regenerate the ball bitmap.
//
void CBounceWin::MakeNewBall(void)
{
if(m_pBitmap != NULL)
{
// Reclaim Windows resources associated with the ball bitmap
// before redrawing
m_pBitmap->DeleteObject();
}
else
m_pBitmap = new CBitmap;
m_cxTotal = (m_cxRadius + ABS(m_cxMove)) << 1;
m_cyTotal = (m_cyRadius + ABS(m_cyMove)) << 1;
CDC dcMem;
CDC* pDC = GetDC();
dcMem.CreateCompatibleDC(pDC);
m_pBitmap->CreateCompatibleBitmap(pDC, m_cxTotal, m_cyTotal);
ASSERT(m_pBitmap->m_hObject != NULL);
ReleaseDC(pDC);
CBitmap* pOldBitmap = dcMem.SelectObject(m_pBitmap);
// draw a rectangle in the background (window) color
CRect rect(0, 0, m_cxTotal, m_cyTotal);
CBrush brBackground(::GetSysColor(COLOR_WINDOW));
dcMem.FillRect(rect, &brBackground);
CBrush brCross(HS_DIAGCROSS, 0L);
CBrush* pOldBrush = dcMem.SelectObject(&brCross);
dcMem.SetBkColor(m_clrBall);
dcMem.Ellipse(ABS(m_cxMove), ABS(m_cyMove),
m_cxTotal - ABS(m_cxMove), m_cyTotal - ABS(m_cyMove));
dcMem.SelectObject(pOldBrush);
dcMem.SelectObject(pOldBitmap);
dcMem.DeleteDC();
}
// OnSize: ball size and displacement change according to the window size.
void CBounceWin::OnSize(UINT nType, int cx, int cy)
{
m_xCenter = (m_cxClient = cx) >> 1;
m_yCenter = (m_cyClient = cy) >> 1;
m_xCenter += m_cxClient >> 3; // make the ball a little off-center
LONG lScale = min((LONG)m_cxClient * m_xPixel,
(LONG)m_cyClient * m_yPixel) >> 4;
m_cxRadius = (short)(lScale / m_xPixel);
m_cyRadius = (short)(lScale / m_yPixel);
m_cxMove = max(1, m_cyRadius >> 2);
m_cyMove = max(1, m_cyRadius >> 2);
MakeNewBall();
CMDIChildWnd::OnSize(nType, cx, cy);
}
// OnColor: ball color needs to be changed. Checkmark the right color on the
// menu.
void CBounceWin::OnColor(void)
{
CMenu* pMenu = GetMDIFrame()->GetMenu();
pMenu->CheckMenuItem(m_nColor, MF_UNCHECKED);
m_nColor = GetCurrentMessage()->wParam;
pMenu->CheckMenuItem(m_nColor, MF_CHECKED);
if(m_nColor != IDM_CUSTOM)
m_clrBall = clrTextArray[m_nColor - IDM_BLACK];
else
{
CColorDialog dlgColor(m_clrBall);
if(dlgColor.DoModal() == IDOK)
m_clrBall = dlgColor.GetColor();
}
MakeNewBall();
Invalidate();
}
// OnSpeed: ball speed needs to be changed. Checkmark the menus, kill the
// current timer and start a new one at the new speed.
void CBounceWin::OnSpeed(void)
{
CMenu* pMenu = GetMDIFrame()->GetMenu();
pMenu->CheckMenuItem(m_nSpeed, MF_UNCHECKED);
m_nSpeed = GetCurrentMessage()->wParam;
pMenu->CheckMenuItem(m_nSpeed, MF_CHECKED);
KillTimer(1);
if(!SetTimer(1,(m_nSpeed==IDM_SLOW? 100 : 0), NULL))
{
MessageBox("Not enough timers available for this window.",
"Viewer:Bounce", MB_ICONEXCLAMATION | MB_OK);
m_nSpeed = 0;
DestroyWindow();
}
}
// OnTimer: Animate the ball.
void CBounceWin::OnTimer(UINT)
{
if(m_pBitmap != NULL)
{
CDC* pdcScreen = GetDC();
CDC dcMem;
dcMem.CreateCompatibleDC(pdcScreen);
ASSERT(m_pBitmap->m_hObject != NULL);
CBitmap* pOldMap = dcMem.SelectObject(m_pBitmap);
pdcScreen->BitBlt(m_xCenter - m_cxTotal / 2,
m_yCenter - m_cyTotal / 2, m_cxTotal, m_cyTotal,
&dcMem, 0, 0, SRCCOPY);
ReleaseDC(pdcScreen);
m_xCenter += m_cxMove;
m_yCenter += m_cyMove;
if((m_xCenter + m_cxRadius >= m_cxClient) ||
(m_xCenter - m_cxRadius <= 0))
m_cxMove = -m_cxMove;
if((m_yCenter + m_cyRadius >= m_cyClient) ||
(m_yCenter - m_cyRadius <= 0))
m_cyMove = -m_cyMove;
dcMem.SelectObject(pOldMap);
dcMem.DeleteDC();
}
}
// OnMDIActivate:
// The current window is being activated or deactivated.
// Change MDI frame window menu as appropriate.
//
void CBounceWin::OnMDIActivate(BOOL bActivate, CWnd*, CWnd*)
{
CMDIFrameWnd* pFrame = GetMDIFrame();
CMenu* pWinPopupMenu = NULL;
CMenu* pMenu = new CMenu;
m_bWindowActive = bActivate;
if(bActivate)
{
pMenu->LoadMenu("Bounce");
pWinPopupMenu = pMenu->GetSubMenu(BOUNCE_MENU_POS);
CMenu* pLastMenu = pFrame->MDISetMenu(pMenu, pWinPopupMenu);
pLastMenu->DestroyMenu();
pMenu->CheckMenuItem(m_nColor, bActivate ? MF_CHECKED : MF_UNCHECKED);
pMenu->CheckMenuItem(m_nSpeed, bActivate ? MF_CHECKED : MF_UNCHECKED);
}
else
{
pMenu->LoadMenu("Init");
pWinPopupMenu = pMenu->GetSubMenu(INIT_MENU_POS);
CMenu* pLastMenu = pFrame->MDISetMenu(pMenu, pWinPopupMenu);
pLastMenu->DestroyMenu();
}
delete m_pMenuCurrent;
m_pMenuCurrent = pMenu;
pFrame->DrawMenuBar();
}